﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using popLib;
using System.Reflection;
using popLib.CustomeControl;
using popLib.ModelSystem;
using popLib.ExtensionClass;

namespace popLib.ModelSystem
{
    public abstract class DetailBase: Form
    {
        #region properties
        /// <summary>
        /// id cua record dang sua chua, co the la INT or STRING, co gia tri khi dang UpdateMode = true, duoc thiet lap qua constructor hoac sau khi save
        /// </summary>
        public object ID { get; set; }

        /// <summary>
        /// object chua thong tin cua mot record dang sua chua, duoc fill vao khi goi ham LoadCurrentRecord
        /// </summary>
        public object Record { get; set; }

        /// <summary>
        /// ActionForm chua thong tin ve phan quyen (right) cua nguoi dung tren form nay
        /// </summary>
        public FormAction Action { get; set; }

        /// <summary>
        /// class dung de quan ly tinh trang form, quan ly cac button (xem, them, huy, luu..), chua cac ham de validate control
        /// </summary>
        public FormValidation FormValidator { get; set; }

        /// <summary>
        /// UpdateMode xac dinh form dang duoc khoi tao de add new record hay la de update record cu, khoi tao trong constructor
        /// </summary>
        public bool UpdateMode { get; set; }

        /// <summary>
        /// thuoc tinh nay giup cho biet form da co sua chua va save record chua -> tu do, co the update form ListBase
        /// </summary>
        public bool IsDatabaseChanged { get; set; }

        /// <summary>
        /// Tieu de cua form, duoc dung trong cac message thong bao
        /// </summary>
        public string FormTitle { get; set; }

        /// <summary>
        /// Xac dinh control nao la control quan ly tinh trang cua form (danh cho quan ly chung tu co tinh trang Moi, XacNhan, Huy), neu ko co thiet lap se ko goi duoc ham ButtonDispose
        /// </summary>
        public ComboBox TinhTrangControl { get; set; }

        /// <summary>
        /// Neu co ly do huy control, thi set control nay, neu co, khi huy chung tu se show len phan go ly do huy vao, else chi show yes no
        /// </summary>
        public TextBox LyDoHuyControl { get; set; }

        /// <summary>
        /// Enum xac dinh cac truong hop thuc hien sau khi add new 1 record
        /// </summary>
        public enum ActionAfterAddNewType {
            ConfirmAddMoreElseCloseForm,
            ConfirmAddMoreElseBackUpdateMode,
            CloseForm,
            UpdateMode
        }
        
        /// <summary>
        /// Thiet lap action sau khi add new record, default la ConfirmAddMoreElseCloseForm
        /// </summary>
        public ActionAfterAddNewType ActionAfterAddNew { get; set; }

        #endregion

        #region button properties
        public Button BtnSave { get; set; }
        public Button BtnUpdate { get; set; }
        public Button BtnDispose { get; set; }
        public Button BtnCancel { get; set; }
        public Button BtnAdd { get; set; }
        public Button BtnConfirm { get; set; }
        public Button BtnPrint { get; set; }
        public Button BtnCopy { get; set; }
        public FlowLayoutPanel LeftContainer { get; set; }
        public FlowLayoutPanel RightContainer { get; set; }
        #endregion

        #region contructor
        public DetailBase(FormAction action, object id)
        {
            Action = action;

            ID = id;

            UpdateMode = true;

            InitializeAll();
        }

        public DetailBase(FormAction action)
        {
            Action = action;

            UpdateMode = false;

            InitializeAll();
        }

        public DetailBase() 
        {
            InitializeAll();
        }
        #endregion

        #region abstract functions
        /// <summary>
        /// goi ham InitializeComponent, de thuc thi trong contructor
        /// </summary>
        public abstract void InitializeInterface();

        /// <summary>
        /// load du lieu co ban luc dau cho form, vd init data cho combobox, formtitle, datagridview structure, form's event...
        /// </summary>
        public abstract void FormLoad();

        /// <summary>
        /// init lai tinh trang cua nut, reset lai data, reset lai thuoc tinh cua cac control
        /// </summary>
        public abstract void ButtonAdd();

        /// <summary>
        /// goi lenh in o day
        /// </summary>
        public abstract void ButtonPrint();

        /// <summary>
        /// goi lenh nhan doi o day
        /// </summary>
        public abstract void ButtonCopy();

        /// <summary>
        /// cap nhat tinh trang cac nut tuy vao action cua form
        /// </summary>
        public abstract void UpdateFormAction();

        /// <summary>
        /// khoi tao validation, them cac control vao list de formvalidator quan ly
        /// </summary>
        public abstract void InitFormValidation();

        /// <summary>
        /// Ham nay load du lieu do vao RECORD by ID va load du lieu cho cac object khac vidu nhu cac record chi tiet
        /// </summary>
        public abstract void LoadCurrentRecord();

        /// <summary>
        /// ham nay do du lieu tu RECORD va cac chitiet vao form
        /// </summary>
        public abstract void FillData();

        /// <summary>
        /// sau khi view detail, thi se lam gi nua, bo dzo day, truoc khi changestate
        /// </summary>
        public abstract void PrepareBeforViewDetail();

        /// <summary>
        /// truoc khi changestate sang update, ban muon lam gi thi dua dzo day
        /// </summary>
        public abstract void PrepareBeforUpdate();

        /// <summary>
        /// truoc khi changestate sang ready, muon lam gi thi dua dzo day
        /// </summary>
        public abstract void PrepareBeforCancel();

        /// <summary>
        /// validate du lieu, rang buoc truoc khi save, neu ok return true
        /// </summary>
        /// <returns>neu ok return true</returns>
        public abstract bool ValidateBeforSave();

        /// <summary>
        /// validate du lieu, rang buoc, neu ok return true
        /// </summary>
        /// <returns>neu ok return true</returns>
        public abstract bool ValidateBeforDispose();

        /// <summary>
        /// sau khi save, muon lam gi thi dua dzo day, vd: ban co muon in hay khong ? in : khong
        /// </summary>
        public abstract void ExecuteAfterSave();

        /// <summary>
        /// Save hoac update du lieu dua tren UPDATEMODE
        /// </summary>
        /// <returns>tra ve RETURNSET(true, ID moi nhat ) neu luu duoc, RETURNSET(false) neu ko thanh cong</returns>
        public abstract ReturnSet SaveOrUpdate();

        
        #endregion

        #region virtual functions
        public virtual void ButtonDispose() {
            if (TinhTrangControl == null) return;
            if (!ValidateBeforDispose()) return;

            ReturnSet result;

            if( LyDoHuyControl != null )
                result = Global.FormMessage(Global.FormMessageType.ConfirmDispose, FormTitle);
            else
                result = Global.FormMessage(Global.FormMessageType.ConfirmDisposeNoReason, FormTitle);

            if (result.Success)
            {
                string currentTinhTrang = TinhTrangControl.SelectedValue.ToString();

                if (LyDoHuyControl != null) LyDoHuyControl.Text = result.Result.ToString();

                TinhTrangControl.SelectedValue = "H";

                if (!ButtonSave())
                {
                    if (LyDoHuyControl != null) LyDoHuyControl.Text = "";
                    TinhTrangControl.SelectedValue = currentTinhTrang;
                }
            }
        }
        public virtual void ButtonConfirm()
        {
            if (TinhTrangControl == null) return;

            if (Global.FormMessage(Global.FormMessageType.ConfirmAccept, FormTitle).Success)
            {
                string currentTinhTrang = TinhTrangControl.SelectedValue.ToString();

                TinhTrangControl.SelectedValue = "XN";

                if (!ButtonSave())
                {
                    TinhTrangControl.SelectedValue = currentTinhTrang;
                }
            }
        }
        public virtual bool ButtonSave()
        {
            if (!ValidateBeforSave()) return false;
            
            ReturnSet result = SaveOrUpdate();
            bool lastUpdateState = UpdateMode;

            if (result.Success)
            {
                ID = result.Result;

                UpdateMode = true;

                FormValidator.AutoClearInput = false;
                ViewDetail();
                FormValidator.AutoClearInput = true;

                UpdateFormAction();

                IsDatabaseChanged = true;

                ExecuteAfterSave();

                FormValidator.ChangeState(FormValidation.FormState.Ready);

                if (lastUpdateState)
                {                    
                    return true;
                }
                else
                {
                    switch (ActionAfterAddNew)
                    {
                        case ActionAfterAddNewType.ConfirmAddMoreElseBackUpdateMode:
                            if (Global.FormMessage(Global.FormMessageType.AddSuccessConfirm, FormTitle).Success)
                            {
                                //BtnAdd.PerformClick(); --> do khong thuc hien trong mot so truong hop 
                                BtnAdd_Click(null, new EventArgs());
                                return true;
                            }
                            else
                            {
                                UpdateMode = true;
                                ViewDetail();
                                UpdateFormAction();
                                return true;
                            }                        
                        case ActionAfterAddNewType.CloseForm:
                            this.Close();
                            return true;                        
                        case ActionAfterAddNewType.ConfirmAddMoreElseCloseForm:
                            if (Global.FormMessage(Global.FormMessageType.AddSuccessConfirm, FormTitle).Success)
                            {
                                //BtnAdd.PerformClick(); --> do khong thuc hien trong mot so truong hop 
                                BtnAdd_Click(null, new EventArgs());
                                return true;
                            }
                            else
                            {
                                this.Close();
                                return true;
                            }
                        case ActionAfterAddNewType.UpdateMode:
                            UpdateMode = true;
                            ViewDetail();
                            UpdateFormAction();
                            return true;
                        default: 
                            return true;
                    }
                }
            }
            else
            {
                Global.FormMessageType messageType = UpdateMode ? Global.FormMessageType.UpdateFail : Global.FormMessageType.AddFail;

                if( result.Message.isValid() )
                    Global.FormMessage(messageType, FormTitle, result.Message);
                Global.FormMessage(messageType, FormTitle);
                
                return false;
            }
        }
        public virtual void ButtonCancel()
        {
            if (!Global.FormMessage(Global.FormMessageType.ConfirmCancel, FormTitle).Success)
                return;

            PrepareBeforCancel();

            if (UpdateMode)
            {
                ViewDetail();
            }
            else
            {
                FormValidator.ChangeState(FormValidation.FormState.Ready);
                this.Close();
            }
        }
        public virtual void ButtonUpdate()
        {
            PrepareBeforUpdate();
            FormValidator.ChangeState(FormValidation.FormState.UpdateCurrent);
        }
        public virtual void ExecuteViewDetail(object ID)
        {
            if (FormValidator.CurrentFormState == FormValidation.FormState.Ready)
            {
                this.ID = ID;

                UpdateMode = true;

                ViewDetail();

                UpdateFormAction();
            }
            else
            {
                FormLib.alert("Bạn đang cập nhật/thêm mới thông tin!!\r\nXin vui lòng hoàn tất trước khi xem chứng từ khác.", "Thông báo");
            }
        }
        public virtual void ExecuteAddNew()
        {
            if (FormValidator.CurrentFormState == FormValidation.FormState.Ready)
            {
                //BtnAdd.PerformClick(); --> do khong thuc hien trong mot so truong hop 
                BtnAdd_Click(null, new EventArgs());
            }
            else
            {
                FormLib.alert("Bạn đang cập nhật/thêm mới thông tin!!\r\nXin vui lòng hoàn tất trước khi xem chứng từ khác.", "Thông báo");
            }
        }
        public virtual void ViewDetail()
        {
            if (UpdateMode)
            {                
                LoadCurrentRecord();
                FillData();

                //update something here if require for example show lydohuy if chung tu la H
                PrepareBeforViewDetail();
                
                //change state to update form title
                FormValidator.ChangeState(FormValidation.FormState.Ready);
            }
            else
            {
                //BtnAdd.PerformClick(); --> do khong thuc hien trong mot so truong hop 
                BtnAdd_Click(null, new EventArgs());
            }
        }
        public virtual void FormStateChanged(FormValidation.FormState state)
        {
            switch (state)
            {
                default:
                case FormValidation.FormState.Ready:
                    this.Text = FormTitle;
                    break;
                case FormValidation.FormState.CreateNew:
                    this.Text = FormTitle + " - Thêm mới";
                    break;
                case FormValidation.FormState.UpdateCurrent:
                    this.Text = FormTitle + " - Cập nhật";
                    break;
            }
        }
        public void InitializeAll()
        {
            this.Icon = MainFormModel.Instance.AppIconSmall;

            InitializeInterface();

            BtnAdd = new Button();
            BtnCancel = new Button();
            BtnUpdate = new Button();
            BtnDispose = new Button();
            BtnConfirm = new Button();
            BtnSave = new Button();
            BtnPrint = new Button();
            BtnCopy = new Button();

            BtnCopy.Text = "Nhân đôi";
            BtnCopy.Visible = false; //mac dinh ko co hien nut NHAN DOI

            LeftContainer = new FlowLayoutPanel();
            LeftContainer.Width = 550;
            LeftContainer.Controls.AddRange(new Control[] { BtnAdd, BtnUpdate, BtnConfirm, BtnDispose, BtnPrint, BtnCopy });
            LeftContainer.Dock = DockStyle.Left;

            RightContainer = new FlowLayoutPanel();
            RightContainer.FlowDirection = FlowDirection.RightToLeft;
            RightContainer.Controls.AddRange(new Control[] { BtnSave, BtnCancel });
            RightContainer.Dock = DockStyle.Fill;
            LeftContainer.Padding = RightContainer.Padding = new Padding(5);

            var TPanel = new Panel();
            TPanel.Dock = DockStyle.Top;
            TPanel.Size = new Size(this.Width, 36);
            TPanel.Controls.AddRange(new Control[] { LeftContainer, RightContainer });
            this.Controls.Add(TPanel);

            this.StartPosition = FormStartPosition.CenterScreen;
            FormValidator = new FormValidation(this);
            Global.InitDetailFormButton(this, BtnAdd, BtnUpdate, BtnConfirm, BtnDispose, BtnCancel, BtnSave, BtnPrint);
            FormValidator.InitNavigatorForm(BtnAdd, BtnUpdate, BtnDispose, BtnSave, BtnCancel, BtnConfirm, BtnPrint);            

            this.FormClosing += new FormClosingEventHandler(ModelForm_FormClosing);
            this.Load += new EventHandler(ModelForm_Load);            
            FormValidator.FormStateChanged += new FormValidation.FormStateChangeEvent(FormStateChanged);
            BtnAdd.Click += new EventHandler(BtnAdd_Click);
            BtnCancel.Click += new EventHandler(BtnCancel_Click);
            BtnUpdate.Click += new EventHandler(BtnUpdate_Click);
            BtnDispose.Click += new EventHandler(BtnDispose_Click);
            BtnConfirm.Click += new EventHandler(BtnConfirm_Click);
            BtnSave.Click += new EventHandler(BtnSave_Click);
            BtnPrint.Click += new EventHandler(BtnPrint_Click);
            BtnCopy.Click += new EventHandler(BtnCopy_Click);
        }
        #endregion

        #region form events
        void BtnCopy_Click(object sender, EventArgs e)
        {
            ButtonCopy();
        }
        void BtnPrint_Click(object sender, EventArgs e)
        {
            ButtonPrint();
        }
        void BtnSave_Click(object sender, EventArgs e)
        {
            ButtonSave();
        }
        void BtnConfirm_Click(object sender, EventArgs e)
        {
            ButtonConfirm();
        }
        void BtnDispose_Click(object sender, EventArgs e)
        {
            ButtonDispose();
        }
        void BtnUpdate_Click(object sender, EventArgs e)
        {
            ButtonUpdate();
        }
        void BtnCancel_Click(object sender, EventArgs e)
        {
            ButtonCancel();
        }
        void BtnAdd_Click(object sender, EventArgs e)
        {
            if (!BtnAdd.Enabled || !BtnAdd.Visible) return;
            ButtonAdd();
            ID = null;
        }
        void ModelForm_Load(object sender, EventArgs e)
        {
            FormLoad();

            InitFormValidation();
            ViewDetail();
            UpdateFormAction();
        }
        void ModelForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (FormValidator.CurrentFormState != FormValidation.FormState.Ready)
            {
                if (!Global.FormMessage(Global.FormMessageType.ConfirmCancel, FormTitle).Success)
                {
                    e.Cancel = true;
                    return;
                }
                else
                {
                    this.FormClosing -= new System.Windows.Forms.FormClosingEventHandler(this.ModelForm_FormClosing);
                    this.Close();
                    this.Dispose();
                }
            }
        }
        #endregion

        #region Functions
        public void AddExtraButton(Button button)
        {
            LeftContainer.Controls.Add(button);
        }
        #endregion
    }
}